package com.xu.cloud.common.util;

import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StopWatch;

import java.lang.reflect.Field;
import java.text.DecimalFormat;
import java.util.concurrent.TimeUnit;

/**
 * 性能统计工具类
 *
 * @author xuguan
 * @since 2024/12/30
 */
public class StopWatchV2 extends StopWatch {

    public StopWatchV2() {
    }

    public StopWatchV2(String id) {
        super(id);
    }

    public String shortSummaryMillis() {
        return "StopWatchV2 '" + getId() + "': running time = " + getTotalTimeMillis() + " ms";
    }

    public String prettyPrintMillis() {
        StringBuilder sb = new StringBuilder(shortSummaryMillis());
        sb.append('\n');

        final boolean b;
        try {
            final Field keepTaskList = ReflectionUtils.findField(getClass(), "keepTaskList", boolean.class);
            Assert.notNull(keepTaskList, "field keepTaskList in class StopWatch not exist");
            ReflectionUtils.makeAccessible(keepTaskList);
            b = (boolean) keepTaskList.get(this);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }

        if (!b) {
            sb.append("No task info kept");
        } else {
            sb.append("---------------------------------------------\n");
            sb.append("ms        %        Task name\n");
            sb.append("---------------------------------------------\n");
            DecimalFormat pf = new DecimalFormat("0.00%");
            for (TaskInfo task : getTaskInfo()) {
                sb.append(task.getTimeMillis()).append("    ");
                sb.append(pf.format((double) task.getTimeMillis() / getTotalTimeMillis())).append("      ");
                sb.append(task.getTaskName()).append("\n");
            }
        }
        return sb.toString();
    }

    public static void main(String[] args) {
        StopWatchV2 sw = new StopWatchV2("test");
        sw.start("t1");
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        sw.stop();
        sw.start("t2");
        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        sw.stop();

        System.out.println(sw.prettyPrintMillis());
    }
}
